﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace ApiDemo
{
    // 任务状态
    enum STATE
    {
        STATE_PENDING = 0,
        STATE_RUNNING = 1,
        STATE_WAITING = 2,
        STATE_ERRWAITING = 3,
        STATE_CANCELING = 4,
        STATE_FINISHED = 5,
        STATE_CANCELED = 6,
        STATE_ABORTED = 7,
    }

    // 任务指令
    enum COMMAND
    {
        CMD_VERIFY = 1,
        CMD_CANCEL = 2,
    }

    // 任务指令结果
    enum COMMAND_RESULT
    {
        RES_PENDING = 0,
        RES_OK = 1,
        RES_ERROR = 2,
    }

    class Robot
    {
        public int id { get; set; }
        public string alias { get; set; }
        public int run_state { get; set; }
        public int mission_id { get; set; }
        public STATE mission_state { get; set; }
        public string map_name { get; set; }
        public double x { get; set; }
        public double y { get; set; }
        public double theta { get; set; }
        public double linear_speed { get; set; }
        public double angular_speed { get; set; }
        public float battery { get; set; }
    }
    class MissionStep
    {
        public string map_name { get; set; }
        public int target { get; set; }
        public string target_code { get; set; }
        public string action { get; set; }
    }
    class Mission
    {
        public string ref_uuid { get; set; }
        public string src { get; set; }
        public string description { get; set; }
        public int req_robot { get; set; }
        public int priority { get; set; }
        public MissionStep[] steps { get; set; }
        public int id { get; set; }
        public Int64 create_stamp { get; set; }
        public Int64 finish_stamp { get; set; }
        public int robot_id { get; set; }
        public STATE state { get; set; }
        public string err_msg { get; set; }
    }
    class MissionCommand
    {
        public int id { get; set; }
        public int cmd { get; set; }
        public bool sync { get; set; }
        public int robot_id { get; set; }
        public int mission_id { get; set; }
        public string mission_uuid { get; set; }
        public COMMAND_RESULT result { get; set; }
        public string err_msg { get; set; }
    }
    class ErrorResponse
    {
        public int code { get; set; }
        public string msg { get; set; }
    }

    class Program
    {
        static HttpClient client = new HttpClient();

        static void ShowRobot(Robot r)
        {
            Console.WriteLine($"Id: {r.id}\tName: {r.alias}\tState: {r.run_state}\tBattery: {r.battery}\tMap: {r.map_name}\tX: {r.x}\tY: {r.y}");
        }

        static void ShowMission(Mission m)
        {
            Console.WriteLine($"Id: {m.id}\tUUID: {m.ref_uuid}Src: {m.src}\tReqRobot: {m.req_robot}\tRobotId: {m.robot_id}\tState: {m.state}\tsteps: {m.steps.Length}");
            for (int i=0; i<m.steps.Length; i++)
            {
                Console.WriteLine($"\tStep#{i}\tMap: {m.steps[i].map_name}\tTarget: {m.steps[i].target}\tAction: {m.steps[i].action}");
            }
        }

        static void ShowMissionCommand(MissionCommand mc)
        {
            Console.WriteLine($"Id: {mc.id}\tMissionUUID: {mc.mission_uuid}MissionId: {mc.mission_id}\tSync: {mc.sync}\tResult: {mc.result}\tErrMsg: {mc.err_msg}");
        }

        static void ShowError(ErrorResponse err)
        {
            Console.WriteLine($"code: {err.code}\tmsg: {err.msg}");
        }

        static async Task<Robot> GetOneRobotAsync(int id)
        {
            Robot r = null;
            HttpResponseMessage response = await client.GetAsync($"/api/v1/robots/{id}");
            if (response.IsSuccessStatusCode)
            {
                r = await response.Content.ReadAsAsync<Robot>();
            }
            else
            {
                ErrorResponse err = await response.Content.ReadAsAsync<ErrorResponse>();
                ShowError(err);
            }
            return r;
        }

        static async Task<Robot[]> GetAllRobotsAsync()
        {
            Robot[] robs = null;
            HttpResponseMessage response = await client.GetAsync("/api/v1/robots");
            if (response.IsSuccessStatusCode) {
                robs = await response.Content.ReadAsAsync<Robot[]>();
            }
            else
            {
                ErrorResponse err = await response.Content.ReadAsAsync<ErrorResponse>();
                ShowError(err);
            }
            return robs;
        }

        static async Task<Mission> CreateMissionAsync(Mission m)
        {
            HttpResponseMessage response = await client.PostAsJsonAsync("/api/v1/missions", m);
            if (response.IsSuccessStatusCode)
            {
                m = await response.Content.ReadAsAsync<Mission>();
            }
            else
            {
                ErrorResponse err = await response.Content.ReadAsAsync<ErrorResponse>();
                ShowError(err);
            };
            return m;
        }

        static async Task<Mission> GetOneMissionAsync(int id)
        {
            Mission m = null;
            HttpResponseMessage response = await client.GetAsync($"/api/v1/missions/{id}");
            if (response.IsSuccessStatusCode)
            {
                m = await response.Content.ReadAsAsync<Mission>();
            }
            else
            {
                ErrorResponse err = await response.Content.ReadAsAsync<ErrorResponse>();
                ShowError(err);
            }
            return m;
        }

        static async Task<Mission> GetOneMissionByUUIDAsync(string uuid)
        {
            Mission m = null;
            HttpResponseMessage response = await client.GetAsync($"/api/v1/uuid/missions/{uuid}");
            if (response.IsSuccessStatusCode)
            {
                m = await response.Content.ReadAsAsync<Mission>();
            }
            else
            {
                ErrorResponse err = await response.Content.ReadAsAsync<ErrorResponse>();
                ShowError(err);
            }
            return m;
        }

        static async Task<MissionCommand> CreateMissionCommandAsync(MissionCommand mc)
        {
            HttpResponseMessage response = await client.PostAsJsonAsync("/api/v1/mscmds", mc);
            if (response.IsSuccessStatusCode)
            {
                mc = await response.Content.ReadAsAsync<MissionCommand>();
            }
            else
            {
                Console.WriteLine(await response.Content.ReadAsStringAsync());
            };
            return mc;
        }

        static async Task<MissionCommand> GetMissionCommandAsync(int id)
        {
            MissionCommand mc = null;
            HttpResponseMessage response = await client.GetAsync($"/api/v1/mscmds/{id}");
            if (response.IsSuccessStatusCode)
            {
                mc = await response.Content.ReadAsAsync<MissionCommand>();
            }
            else
            {
                ErrorResponse err = await response.Content.ReadAsAsync<ErrorResponse>();
                ShowError(err);
            }
            return mc;
        }

        static async Task RunAsync()
        {
            client.BaseAddress = new Uri("http://172.18.120.31:8858/");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            // 查询单个机器人状态
            Robot r = await GetOneRobotAsync(1);
            ShowRobot(r);

            // 查询所有机器人状态
            Robot[] robs = await GetAllRobotsAsync();
            if (robs.Length>0) {
                for (int i = 0; i < robs.Length; i++)
                {
                    ShowRobot(robs[i]);
                }
            }
            else
            {
                Console.WriteLine("No robots selected.");
            }

            // 查询单个任务状态
            Mission m = await GetOneMissionAsync(1);
            ShowMission(m);

            // 新建任务
            string uuid = "hello-my-mission";
            Mission newm = new Mission
            {
                ref_uuid = uuid,
                src = "apidemo",
                priority = 3,
                req_robot = 1,
                steps = new MissionStep[] {
                    new MissionStep{ map_name="test", target=3, action="load"},
                    new MissionStep{ map_name="test", target=5, action="unload"},
                },
            };
            newm = await CreateMissionAsync(newm);
            if (newm.id != 0)
            {
                Console.WriteLine("create mission successful");
                ShowMission(newm);
            }
            else
            {
                Console.WriteLine("create mission failed.");
            }

            // 根据uuid查询任务状态
            newm = await GetOneMissionByUUIDAsync(uuid);
            ShowMission(newm);

            // 取消任务
            MissionCommand mc = new MissionCommand { mission_uuid = uuid, cmd=1, sync=true };
            mc = await CreateMissionCommandAsync(mc);
            ShowMissionCommand(mc);
        }

        static void Main(string[] args)
        {
            try
            {
                RunAsync().Wait();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                if (e.InnerException != null)
                {
                    Console.WriteLine(e.InnerException.Message);
                }
            }
            Console.WriteLine("Press Enter to exit...");
            Console.ReadLine();
        }
    }
}
